// 用于拼接字符串（自动插入换行）并替换到代码文件的类
function myString(dfText) {
    this.val = dfText || ''
    this.add = text => (this.val += (text || '') + '\r\n')
    this.writeTo = (strCode,tag) => {
        return strCode.replace(new RegExp(`\\@${tag},?`, 'g'), this.val.trimLeft())
    }
}



function setDtoRes(tables,ptable,str,allTables){
    if(tables.length>0){
        str.add(`            if(res.${window.$upFirst(ptable.className)}Entity != null)`)
        str.add(`            {`)
        
        tables.forEach(table =>{
            if(table.relationType == '2'){
                str.add(`                res.${window.$upFirst(table.className)}List = await _i${window.$upFirst(table.className)}BLL.GetList(new ${window.$upFirst(table.className)}Entity { ${window.$upFirst(table.field)} = res.${window.$upFirst(ptable.className)}Entity.${window.$upFirst(table.relationField)} });`)
            }
            else{
                str.add(`                res.${window.$upFirst(table.className)}Entity = await _i${window.$upFirst(table.className)}BLL.GetRelateEntity(res.${window.$upFirst(ptable.className)}Entity.${window.$upFirst(table.relationField)} );`)
            }
        })
        str.add(`            }`)

        tables.forEach(table =>{
            const ctables = allTables.filter(t=>t.relationName == table.name)
            setDtoRes(ctables,table,str,allTables)
        })
    }
}

function setDeleteEntity(tables,ptable,method,allTables){
    if(tables.length>0){
        method.add(`                if(res.${window.$upFirst(ptable.className)}Entity != null)`)
        method.add(`                {`)
        tables.forEach(table=>{
            method.add(`                    await _i${window.$upFirst(table.className)}BLL.DeleteRelateEntity(res.${window.$upFirst(ptable.className)}Entity.${window.$upFirst(table.relationField)});`)
            
        })
        method.add(`                }`)

        tables.forEach(table =>{
            const ctables = allTables.filter(t=>t.relationName == table.name)
            setDeleteEntity(ctables,table,method,allTables)
        })
    }
}

function setSaveEntity(tables,ptable,method,allTables){
    if(tables.length>0){
        tables.forEach(table=>{
           


            //method.add(`                await _i${table.className}BLL.DeleteRelateEntity(dto.${ptable.className}Entity.${window.$upFirst(table.relationField)});`)
            if(table.relationType == '1'){
                const ctables = allTables.filter(t=>t.relationName == table.name)
                // 如果是1对1的关系
                method.add(`                dto.${table.className}Entity.${window.$upFirst(table.field)} = dto.${ptable.className}Entity.${window.$upFirst(table.relationField)};`)
                const cMap = {}
                ctables.forEach(ctable => {
                    if(!cMap[ctable.relationField]){
                        method.add(`                if(string.IsNullOrEmpty(dto.${table.className}Entity.${window.$upFirst(ctable.relationField)}))`)
                        method.add(`                {`)
                        method.add(`                    dto.${table.className}Entity.${window.$upFirst(ctable.relationField)} = Guid.NewGuid().ToString();`)
                        method.add(`                }`)
                        cMap[ctable.relationField] = true
                    }
                })

                if(table.relationField == ptable.columns.find(t=>t.isPrimary).name){
                    method.add(`                await _i${table.className}BLL.SaveEntity(string.IsNullOrEmpty(keyValue)?null:dto.${table.className}Entity.${window.$upFirst(table.columns.find(t=>t.isPrimary).name)},dto.${table.className}Entity);`)
                }
                else{
                    method.add(`                await _i${table.className}BLL.SaveEntity(dto.${table.className}Entity.${window.$upFirst(table.columns.find(t=>t.isPrimary).name)},dto.${table.className}Entity);`)
                }
                
                setSaveEntity(ctables,table,method,allTables)
            }
            else{
                // 如果是2对2的关系
                //method.add(`                foreach(var item in dto.${window.$upFirst(table.className)}List)`)
                //method.add(`                {`)
                //method.add(`                    item.${window.$upFirst(table.field)} = dto.${ptable.className}Entity.${window.$upFirst(table.relationField)};`)
                method.add(`                await _i${table.className}BLL.SaveList(dto.${ptable.className}Entity.${window.$upFirst(table.relationField)},dto.${window.$upFirst(table.className)}List);`)
                //method.add(`                }`)
            }
        })
    }
}


export const generatorBll = (setting,temp,table)=>{
    let strCode = temp
    temp = null

    if(setting.namespace.ibll != 'learun.iapplication'){
        strCode = strCode.replace('@IBLLNamespace',`using ${setting.namespace.ibll}`)
    }
    else{
        strCode = strCode.replace('@IBLLNamespace','')
    }
    
    strCode = strCode.replace('@Namespace',setting.namespace.bll)
    strCode = strCode.replace('@ProjectName',`${setting.project.f_Name}-${setting.moduleName}`)
    strCode = strCode.replace('@CompanyName',setting.company)
    strCode = strCode.replace('@CreateUserName',setting.userInfo.f_RealName)
    strCode = strCode.replace('@Datetime',setting.createTime)
    strCode = strCode.replace(/@Des/g,`${setting.des}`)
    
    strCode = strCode.replace('@IBLLName',`I${window.$upFirst(table.className)}BLL`)
    strCode = strCode.replace(/@ServiceName/g,`${window.$upFirst(table.className)}Service`)

    // 主表处理
    let tableMethod = new myString()
    var deleteMethod = new myString()
    let saveMethod = new myString()
    // 构造方法处理
    var initMethod = new myString()
    if(table.type == 'main'){

       
        if(setting.dbTable.length >1){
            let ibllName = ''
            const cdbTable = setting.dbTable.filter(t=>t.name != table.name)
            cdbTable.forEach(ctable => {
                ibllName += `I${window.$upFirst(ctable.className)}BLL i${window.$upFirst(ctable.className)}BLL,`
                initMethod.add(`        private readonly I${window.$upFirst(ctable.className)}BLL _i${window.$upFirst(ctable.className)}BLL;`)
            })
            initMethod.add(`        /// <summary>`)
            initMethod.add(`        /// 构造方法`)
            initMethod.add(`        /// <summary>`)
            cdbTable.forEach(ctable => {
                initMethod.add(`        /// <param name="i${window.$upFirst(ctable.className)}BLL">${ctable.comment}接口</param>`)
            })
            initMethod.add(`        public @ClassName(${ibllName.substring(0,ibllName.length-1)})`)
            initMethod.add('        {')
            cdbTable.forEach(ctable => {
                initMethod.add(`            _i${window.$upFirst(ctable.className)}BLL = i${window.$upFirst(ctable.className)}BLL?? throw new ArgumentNullException(nameof(i${window.$upFirst(ctable.className)}BLL));`)
            })
            initMethod.add('        }')
        }

        


        if(setting.qTables.length > 1){
            tableMethod.add(`        /// <summary>`)
            tableMethod.add(`        /// 获取@Des的列表数据`)
            tableMethod.add(`        /// <summary>`)
            tableMethod.add(`        /// <param name="queryParams">查询参数</param>`)
            tableMethod.add(`        /// <returns></returns>`)
            
            tableMethod.add(`        public Task<IEnumerable<@MainTableEntity>> GetRelateList(@MainTableEntity queryParams)`)
            tableMethod.add(`        {`)
            tableMethod.add(`            return @serviceName.GetRelateList(queryParams);`)
            tableMethod.add(`        }`)

            tableMethod.add(`        /// <summary>`)
            tableMethod.add(`        /// 获取@Des的分页数据`)
            tableMethod.add(`        /// <summary>`)
            tableMethod.add(`        /// <param name="pagination">分页参数</param>`)
            tableMethod.add(`        /// <param name="queryParams">查询参数</param>`)
            tableMethod.add(`        /// <returns></returns>`)
            
            tableMethod.add(`        public Task<IEnumerable<@MainTableEntity>> GetRelatePageList(Pagination pagination, @MainTableEntity queryParams)`)
            tableMethod.add(`        {`)
            tableMethod.add(`            return @serviceName.GetRelatePageList(pagination, queryParams);`)
            tableMethod.add(`        }`)
        }

        if(setting.dbTable.length > 1)  {
            const cdbTables = setting.dbTable.filter(t=>t.relationName == table.name)

            // 保存方法
            saveMethod.add(`        /// <summary>`)
            saveMethod.add(`        /// 保存实体`)
            saveMethod.add(`        /// </summary>`)
            saveMethod.add(`        /// <param name="keyValue">主键</param>`)
            saveMethod.add(`        /// <param name="dto">数据集合</param>`)  
            saveMethod.add(`        /// <returns></returns>`)
            saveMethod.add(`        public async Task SaveAll(@PkType keyValue, ${window.$upFirst(setting.name)}Dto dto)`)
            saveMethod.add(`        {`)
            saveMethod.add('            @serviceName.BeginTrans();')
            saveMethod.add(`            try`)
            saveMethod.add(`            {`)

            const cMap = {}

            cdbTables.forEach(ctable => {
                if(!cMap[ctable.relationField]){
                    saveMethod.add(`                if(string.IsNullOrEmpty(dto.${table.className}Entity.${window.$upFirst(ctable.relationField)}))`)
                    saveMethod.add(`                {`)
                    saveMethod.add(`                    dto.${table.className}Entity.${window.$upFirst(ctable.relationField)} = Guid.NewGuid().ToString();`)
                    saveMethod.add(`                }`)
                    cMap[ctable.relationField] = true
                }
                
            })

            saveMethod.add(`                await SaveEntity(keyValue,dto.${table.className}Entity);`)
            setSaveEntity(cdbTables,table,saveMethod,setting.dbTable)


            saveMethod.add(`                @serviceName.Commit();`)
            saveMethod.add(`            }`)
            saveMethod.add(`            catch (Exception)`)
            saveMethod.add(`            {`)
            saveMethod.add(`                @serviceName.Rollback();`)
            saveMethod.add(`                throw;`)
            saveMethod.add(`            }`)
            saveMethod.add(`        }`)

            // 删除方法
            deleteMethod.add(`        /// <summary>`)
            deleteMethod.add(`        /// 删除实体`)
            deleteMethod.add(`        /// </summary>`)   
            deleteMethod.add(`        /// <param name="keyValue">主键</param>`)  
            deleteMethod.add(`        /// <returns></returns>`)
            deleteMethod.add(`        public async Task DeleteAll(@PkType keyValue)`)
            deleteMethod.add(`        {`)
            deleteMethod.add(`            var res = new ${window.$upFirst(setting.name)}Dto();`)
            deleteMethod.add(`            res.${table.className}Entity = await GetEntity(keyValue);`)
            
            setDtoRes(cdbTables,table,deleteMethod, setting.dbTable)
            deleteMethod.add('            @serviceName.BeginTrans();')
            deleteMethod.add(`            try`)
            deleteMethod.add(`            {`)
            deleteMethod.add(`                await Delete(keyValue);`)
            setDeleteEntity(cdbTables,table,deleteMethod,setting.dbTable)

            deleteMethod.add(`                @serviceName.Commit();`)
            deleteMethod.add(`            }`)
            deleteMethod.add(`            catch (Exception)`)
            deleteMethod.add(`            {`)
            deleteMethod.add(`                @serviceName.Rollback();`)
            deleteMethod.add(`                throw;`)
            deleteMethod.add(`            }`)
            
            deleteMethod.add(`        }`)
        } 
    }
    else{ // 子表处理
        if(table.relationType == '1'){
            tableMethod.add(`        /// <summary>`)
            tableMethod.add(`        /// 获取@Des的实体根据外键`)
            tableMethod.add(`        /// <summary>`)
            tableMethod.add(`        /// <param name="key">关联键</param>`)
            tableMethod.add(`        /// <returns></returns>`)
            tableMethod.add(`        public Task<@MainTableEntity> GetRelateEntity(string key) {`)
            tableMethod.add(`            return @serviceName.GetRelateEntity(key);`)
            tableMethod.add(`        }`)
        }
        else{
            saveMethod.add(`        /// <summary>`)
            saveMethod.add(`        /// 保存子表数据`)
            saveMethod.add(`        /// <summary>`)
            saveMethod.add(`        /// <param name="key">外键值</param>`)
            saveMethod.add(`        /// <param name="list">数据集合</param>`)
            saveMethod.add(`        /// <returns></returns>`)
            saveMethod.add(`        public async Task SaveList(string key, IEnumerable<@MainTableEntity> list) {`)
            if(table.columns.findIndex(t=>t.dataType == 'code') > -1){
                saveMethod.add(`            foreach (var item in list)`)
                saveMethod.add(`            {`)
                table.columns.forEach(col=>{
                    if(col.dataType == 'code'){
                        saveMethod.add(`                item.${window.$upFirst(col.name)} = (await GetRuleCodeEx(item.${window.$upFirst(col.name)})).ToString(); `)
                    }
                })
                saveMethod.add(`            }`)
            }
           
            saveMethod.add(`            await @serviceName.SaveList(key,list);`)
            saveMethod.add(`        }`)
        }

        deleteMethod.add(`        /// <summary>`)
        deleteMethod.add(`        /// 删除@Des的实体根据外键`)
        deleteMethod.add(`        /// <summary>`)
        deleteMethod.add(`        /// <param name="key">关联键</param>`)
        deleteMethod.add(`        /// <returns></returns>`)
        deleteMethod.add(`        public Task DeleteRelateEntity(string key) {`)
        deleteMethod.add(`            return @serviceName.Delete(key);`)
        deleteMethod.add(`        }`)
    }

    strCode = initMethod.writeTo(strCode,'InitMethod')
    initMethod = null

    strCode = tableMethod.writeTo(strCode,'TableMethod')
    tableMethod = null

    strCode = deleteMethod.writeTo(strCode,'DeleteMethod')
    deleteMethod = null

    strCode = saveMethod.writeTo(strCode,'SaveMethod')
    saveMethod = null


    let pkCsType = table.columns.find(t=>t.isPrimary).csType
    if(!['string'].includes(pkCsType)){
        pkCsType += '?'
    }

    // 设置单据编码
    let ruleCode = new myString()
    table.columns.forEach(col=>{
        if(col.dataType == 'code'){
            ruleCode.add(`            entity.${window.$upFirst(col.name)} = (await GetRuleCodeEx(entity.${window.$upFirst(col.name)})).ToString(); `)
        }
    })

    strCode = ruleCode.writeTo(strCode,'RuleCode')
    ruleCode = null


    strCode = strCode.replace(/@PkType/g,`${pkCsType}`)
    strCode = strCode.replace(/@ClassName/g,window.$upFirst(`${table.className}BLL`))
    strCode = strCode.replace(/@serviceName/g,`${window.$lowerFirst(table.className)}Service` )
    strCode = strCode.replace(/@MainTableEntity/g,window.$upFirst(table.className)+ 'Entity')
    return strCode;
}